package cn.fanqinghong.ymcc.service.impl;

import cn.fanqinghong.ymcc.constants.KillActivityConstants;
import cn.fanqinghong.ymcc.constants.KillCourseConstant;
import cn.fanqinghong.ymcc.domain.KillActivity;
import cn.fanqinghong.ymcc.domain.KillCourse;
import cn.fanqinghong.ymcc.mapper.KillActivityMapper;
import cn.fanqinghong.ymcc.service.IKillActivityService;
import cn.fanqinghong.ymcc.service.IKillCourseService;
import cn.fanqinghong.ymcc.util.AssertUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author superman.fan
 * @since 2022-08-04
 */
@Service
@Slf4j
public class KillActivityServiceImpl extends ServiceImpl<KillActivityMapper, KillActivity> implements IKillActivityService {

    @Autowired
    private IKillCourseService killCourseService;
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private RedissonClient redissonClient;
    /**
     * 发布秒杀活动
     * @param activityId
     */
    @Override
    public void publish(Long activityId) {
        //1.查询活动的课程
        List<KillCourse> killCourses = selectByActivityId(activityId);
        AssertUtil.isTrue(killCourses.size() != 0, KillActivityConstants.ACTIVITY_NOT_COURSE);
        KillActivity killActivity = selectById(activityId);
        //获得当前时间是否在活动的额开始时间之前
        boolean startTime = new Date().before(killActivity.getStartTime());
        Date now = new Date();
//        AssertUtil.isTrue(startTime,KillActivityConstants.ACTIVITY_NOT_ONTIME);
        //2.使用hash的形式把活动课程放入redis中，设置秒杀的信号量
        killCourses.forEach(killCourse -> {
            //设置key 活动id：当前秒杀课程的活动id
            String key = activityId + ":" + killCourse.getId();
            //3.设置信号量,课程的秒杀量
            RSemaphore semaphore = redissonClient.getSemaphore(key);
            boolean setPermits = semaphore.trySetPermits(killCourse.getKillCount());
            if (setPermits){
                log.info("保存redis{}",killCourse);
                //4.设置信号量成功，将数据保存到redis
                redisTemplate.opsForHash().put(KillCourseConstant.ACTIVITY_PRE+activityId,killCourse.getId().toString(),killCourse);
                //修改活动课程状态
                killCourse.setPublishTime(now);
                killCourse.setPublishStatus(KillCourse.COURSE_IN_PUBLISH);
                killCourseService.updateById(killCourse);
            }else{
                //5.设置信号量失败，代表本条秒杀信息保存失败
                log.info("课程{}保存redis失败",killCourse.getCourseName());
                /*
                 设置兜底，重试
                 发送信息给运维，该条消息保存失败，手动上传
                 */
            }
        });
        killActivity.setPublishTime(now);
        killActivity.setPublishStatus(KillActivity.ACTIVITY_IS_PUBLISHED);
        updateById(killActivity);
        //6.结束



    }

    public List<KillCourse> selectByActivityId(Long activityId){
        Wrapper<KillCourse> wrapper = new EntityWrapper<>();
        wrapper.eq("activity_id",activityId);
        return killCourseService.selectList(wrapper);
    }
}
